/*******************************************************************************
 * SVN­Versioning-Information:
 * ­­­­­­­­­­­­­­­­­­­­­­­­
 * $LastChangedRevision: 127 $
 * $LastChangedBy: SD $
 * $LastChangedDate: 2009-06-23 12:19:54 +0200 (Tue, 23 Jun 2009) $
 * $HeadURL: svn://lvis10.fbm.fht-stuttgart.de/common/Common/src/de/hft_stuttgart/botwar/common/models/Position.java $
 ******************************************************************************/
package de.hft_stuttgart.botwar.common.models;

import java.io.Serializable;
import java.util.Random;

/**
 * Objects of this class represent a position on the playground
 * @author c.a.duevel@gmail.com
 *
 */
public class Position implements Serializable {
    /**
     * The Error Message used when erratic coordinates are passed
     */
    protected static final String ERROR_MESSAGE = "Erratic coordinates!";
    /**
     * The X_MAX Value for the gaming arena
     */
    public static final double X_MAX = 800.;
    /**
     * The Y_MAX Value for the gaming arena
     */
    public static final double Y_MAX = 550.;
    private double x,  y;
    private static Random random = new Random();

    /**
     * New Position.
     * @param x may not be negative
     * @param y may not be negative
     */
    public Position(final double x, final double y) {
        this.setX(x);
        this.setY(y);
    }

    /**
     * Return x value of a position.
     * @return x value of a position
     */
    public double getX() {
        return x;
    }

    /**
     * Returns y value of a position.
     * @return y value of a position
     */
    public double getY() {
        return y;
    }

    /**
     * Set new X value
     * @param x may not be negative
     */
    public void setX(final double x) {
        checkForIllegalParam(x);
        assert x <= X_MAX : ERROR_MESSAGE;
        this.x = x;
    }

    /**
     * Set new y value
     * @param y may not be negative
     */
    public void setY(final double y) {
        checkForIllegalParam(y);
        assert y <= Y_MAX : ERROR_MESSAGE;
        this.y = y;
    }

    /**
     * Overrides method toString.
     * @return Text representation of this instance.
     */
    @Override
    public String toString() {
        return "Position (" + x + "," + y + ")";
    }

    /**
     * Compares this object to the specified object.  The result is
     * <code>true</code> if and only if the argument is not
     * <code>null</code> and is an <code>Position</code> object that
     * marks the same position as this object.
     *
     * @param obj the object to compare with.
     * @return <code>true</code> if the objects are the same;
     *          <code>false</code> otherwise.
     */
    @Override
    public boolean equals(final Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Position other = (Position) obj;
        if (this.x != other.x) {
            return false;
        }
        if (this.y != other.y) {
            return false;
        }
        return true;
    }

    /**
     * Overrides method hashCode.
     * @return hash code
     */
    @Override
    public int hashCode() {
        int hash = 3;
        hash = 71 * hash + (int) (Double.doubleToLongBits(this.x) ^
                (Double.doubleToLongBits(this.x) >>> 32));
        hash = 71 * hash + (int) (Double.doubleToLongBits(this.y) ^
                (Double.doubleToLongBits(this.y) >>> 32));
        return hash;
    }

    /**
     * Returns the distnace of <code>this</code> to p.
     * @param p The position to measure the distance to.
     * @return distance between p and <code>this</code>
     */
    public double distance(final Position p) {
        if (this.equals(p)) {
            return 0;
        } else {
            return distance(p.getX(), p.getY());
        }

    }

    /**
     * Returns the distnace of <code>this</code> to position x, y.
     * @param x coordinate on x axis
     * @param y coordinate on y axis
     * @return distance of x,y
     */
    public double distance(final double x, final double y) {
        double difx = (double) this.getX() - x;
        double dify = (double) this.getY() - y;
        return Math.pow(difx * difx + dify * dify, 0.5);
    }

    private void checkForIllegalParam(final double x) {
        if (x < 0) {
            throw new IllegalArgumentException("Position can't have negative" +
                    " coordinates");
        }
    }

    /**
     * Creates random position Objects.
     * @return position object - random
     */
    public static Position createRandomPosition() {
        return new Position(Math.abs(random.nextInt() % X_MAX),
                Math.abs(random.nextInt() % Y_MAX));
    }
}
